﻿using Janus.Mes.DTO;
using Janus.Mes.Services;
using Janus.Mes.Services.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using Janus.Cores.Linq;
using Janus.BaseEntitys;
using Janus.Cores;
using System.Diagnostics;
using Janus.ExpressionSerialization;
using System.Collections;
using Janus.Cores.Tools;
using Janus.Cores.Extension;

namespace Tests.Janus.Mes.ServicesConsole
{
    public class IndicatorServicesTest
    {
        IIndicator services = ServiceFactory.Create<IIndicator>();
        public IndicatorServicesTest()
        {
            //this.BatchInsert();
            //this.BatchUpdate();
            //this.Add();
            //this.AddMany();

            //this.Update();
            //this.UpdateMany();
            //this.UpdateSetionByHashtable();
            //this.UpdateSetionByModel();
            //this.UpdateSetionByQuerier();
            //this.UpdateSetionByLamda();
            //this.SaveByUpdate();
            //this.SaveByInsert();
            //this.SaveMany();
            this.UpdateIsEnable();

            //this.DeleteByPK();
            //this.DeleteByConditioner();
            //this.DeleteByLamda();
            //this.DeleteByQuerier();

            //this.FindScalar();
            //this.FindScalarByQuerier();
            //this.FindOne();
            //this.FindOnePredicate();
            //this.FindOneByQuerier();
            //this.FindAll();
            //this.FindAllByQuerier();
            //this.FindAllSearchEntity();
            //this.FindAllByPro();

            //this.IsExists();
            //this.IsExistsByQuerier();

        }
        #region 批量操作
        private List<IndicatorDTO> BatchInsert(int count = 50000)
        {
            var models = new List<IndicatorDTO>();
            for (int i = 1; i <= count; i++)
            {
                var model = new IndicatorDTO();
                model.IndicatorName = i + "测试Add" + DateTime.Now.ToString("yyyyMMddHH");
                model.IndicatorFiledName = i + "Add" + DateTime.Now.ToString("yyyyMMddHH");
                model.Id = model.NewGuid2();
                model.IndicatorValue = i;
                model.IntNotNull = i;
                model.Bit = false;
                model.CreateDt = DateTime.Now.AddDays(i);
                model.CreateDate = DateTime.Now.AddDays(i);
                model.UpdateDate = DateTime.Now.AddDays(i);
                model.Creator = "admin";
                models.Add(model);
            }
            Stopwatch w = new Stopwatch();
            w.Start();
            var result = services.BatchInset(models);
            w.Stop();
            Console.WriteLine("BatchInsert ->{0},耗时：{1}毫秒", result, w.ElapsedMilliseconds);
            return models;
        }

        private void BatchUpdate()
        {
            var models = BatchInsert(500);
            models.ForEach(c => { c.RowState = System.Data.DataRowState.Modified; c.IndicatorFiledName = "BatchUpdate"; c.IndicatorValue = 520; });
            for (int i = 1; i <= 10; i++)
            {
                var model = new IndicatorDTO();
                model.IndicatorName = i + "BatchUpdate" + DateTime.Now.ToString("yyyyMMddHH");
                model.IndicatorFiledName = i + "BatchUpdate" + DateTime.Now.ToString("yyyyMMddHH");
                model.Id = model.NewGuid2();
                model.IndicatorValue = i;
                model.IntNotNull = i;
                model.Bit = false;
                model.CreateDt = DateTime.Now.AddDays(i);
                model.CreateDate = DateTime.Now.AddDays(i);
                model.UpdateDate = DateTime.Now.AddDays(i);
                model.Creator = "admin";
                model.RowState = System.Data.DataRowState.Added;
                models.Add(model);
            }
            Stopwatch w = new Stopwatch();
            w.Start();
            var result = services.BatchUpdate(models);
            w.Stop();
            Console.WriteLine("BatchUpdate ->{0},耗时：{1}毫秒", result, w.ElapsedMilliseconds);
        }
        #endregion

        #region 查询
        public void FindScalar()
        {
            var model = new IndicatorDTO();
            var id = model.NewGuid2();
            this.Add(id);
            //使用表达式转条件
            Expression<Func<IndicatorDTO, string>> updater = (c) => c.IndicatorName;
            Expression<Func<IndicatorDTO, bool>> predicate = (c) => c.Id == id;
            var result = services.FindScalar(updater.GetName(), predicate.ToWhere());
            services.Delete(id);
            Console.WriteLine("FindScalar ->{0}", result != null);
        }
        public void FindScalarByQuerier()
        {
            var model = new IndicatorDTO();
            var id = model.NewGuid2();
            this.Add(id);
            //使用表达式转条件
            Expression<Func<IndicatorDTO, string>> updater = (c) => c.IndicatorName;
            Querier query = new Querier("Id=({@0})", new List<object>() { id });//推荐使用此方式 组装条件
            var result = services.FindScalar(updater.GetName(), query);
            services.Delete(id);
            Console.WriteLine("FindScalar ->{0}", result != null);
        }

        /// <summary>
        /// 主键查找
        /// </summary>
        public void FindOne()
        {
            var model = new IndicatorDTO();
            var id = model.NewGuid2();
            this.Add(id);
            var result = services.FindOne(id);
            services.Delete(id);
            services.Delete(id);
            Console.WriteLine("FindOne ->{0}", result != null);

        }

        /// <summary>
        /// 表达式转SQL
        /// </summary>
        public void FindOnePredicate()
        {
            var model = new IndicatorDTO();
            var id = model.NewGuid2();
            this.Add(id);

            Expression<Func<IndicatorDTO, bool>> predicate = (c) => c.Id == id && c.CreateDate >= DateTime.Now.AddDays(-10);
            var result = services.FindOne(predicate.ToWhere());
            services.Delete(id);
            Console.WriteLine("FindOnePredicate ->{0}", result != null);
        }

        public void FindOneByQuerier()
        {
            var model = new IndicatorDTO();
            var id = model.NewGuid2();
            this.Add(id);
            Querier query = new Querier("Id=({@0}) and CreateDate>={@1}", new List<object>() { id, DateTime.Now.AddDays(-10) });//推荐使用此方式 组装条件
            var result = services.FindOne(query);
            services.Delete(id);
            Console.WriteLine("FindOneByQuerier ->{0}", result != null);
        }

        /// <summary>
        /// 不分页获取所有
        /// </summary>
        public void FindAll()
        {
            //表达式转条件
            Expression<Func<IndicatorDTO, bool>> predicate = (c) => c.CreateDt > DateTime.Now.AddMonths(-10);
            //Querier 转排序
            var orderby = new Querier().OrderBy<IndicatorDTO>(c => c.CreateDt).OrderDescBy<IndicatorDTO>(p => p.IndicatorValue).Orders;
            var result = services.FindAll(predicate.ToWhere(), orderby);
            Console.WriteLine("FindAll ->{0}", result.Count);
        }

        /// <summary>
        /// 不分页获取
        /// </summary>
        public void FindAllByQuerier()
        {
            Querier query = new Querier("CreateDt>=({@0}) and CreateDate>={@1}", new List<object>() { DateTime.Now.AddMonths(-10), DateTime.Now.AddDays(-10) });//推荐使用此方式 组装条件
            query.OrderBy<IndicatorDTO>(c => c.CreateDt).OrderDescBy<IndicatorDTO>(p => p.IndicatorValue);
            var result = services.FindAll(query);
            Console.WriteLine("FindAll ->{0}", result.Count);
        }

        /// <summary>
        /// 分页搜索
        /// </summary>
        public void FindAllSearchEntity()
        {
            PaginationDTO pagination = new PaginationDTO();
            Querier query = new Querier("CreateDt>=({@0}) and CreateDate>={@1}", new List<object>() { DateTime.Now.AddMonths(-10), DateTime.Now.AddDays(-10) })
                .OrderBy<IndicatorDTO>(c => c.CreateDt)
                .OrderDescBy<IndicatorDTO>(p => p.IndicatorValue); //推荐使用此方式 组装条件
            SearchEntity<IndicatorDTO> searchEntity = new SearchEntity<IndicatorDTO>(query, pagination);
            var result = services.FindAll(searchEntity);
            Console.WriteLine("FindAllSearchEntity ->{0}", result.Pagination.RowCount);
        }

        /// <summary>
        /// 分页搜索 存储过程 性能最好
        /// </summary>
        public void FindAllByPro()
        {
            PaginationDTO pagination = new PaginationDTO();
            //like
            PageCriteriaer<IndicatorDTO> searchEntity = new PageCriteriaer<IndicatorDTO>(c => (c.IndicatorName.StartsWith("测试") || c.IndicatorValue > 1) && c.IndicatorFiledName.Contains("测试")
            , pagination
            , "Id");
            searchEntity.OrderBy(c => c.CreateDt).OrderDescBy(c => c.Id);
            var result = services.FindAllByPro(searchEntity.PageCriteria);
            Console.WriteLine("FindAllByPro ->{0}", result.Pagination.RowCount);
        }

        public void IsExists()
        {
            var model = new IndicatorDTO();
            var id = model.NewGuid2();
            this.Add(id);
            Expression<Func<IndicatorDTO, bool>> predicate = (c) => c.Id == id && c.CreateDate >= DateTime.Now.AddDays(-10);
            var result = services.IsExists(predicate.ToWhere());
            services.Delete(id);
            Console.WriteLine("IsExists ->{0}", result);
        }

        public void IsExistsByQuerier()
        {
            var model = new IndicatorDTO();
            var id = model.NewGuid2();
            this.Add(id);
            Querier query = new Querier("Id=({@0}) and CreateDate>={@1}", new List<object>() { id, DateTime.Now.AddDays(-10) });//推荐使用此方式 组装条件
            var result = services.IsExists(query);
            services.Delete(id);
            Console.WriteLine("IsExistsByQuerier ->{0}", result);
        }
        #endregion

        #region 新增
        public void Add(Guid? id = null)
        {
            var model = new IndicatorDTO();
            model.IndicatorName = "测试Add" + DateTime.Now.ToString("yyyyMMddHH");
            model.IndicatorFiledName = "Add" + DateTime.Now.ToString("yyyyMMddHH");
            model.Id = id.HasValue ? id.Value : model.NewGuid2();
            model.IndicatorValue = 123;
            model.IntNotNull = 1;
            model.Bit = false;
            model.CreateDt = DateTime.Now;
            model.CreateDate = DateTime.Now;
            model.UpdateDate = DateTime.Now;
            model.Creator = "admin";
            var result = services.Add(model);
            Console.WriteLine("Add ->{0}", result);
        }

        public List<IndicatorDTO> AddMany(int count = 100)
        {
            var models = new List<IndicatorDTO>();
            for (int i = 1; i <= count; i++)
            {
                var model = new IndicatorDTO();
                model.IndicatorName = i + "测试Add" + DateTime.Now.ToString("yyyyMMddHH");
                model.IndicatorFiledName = i + "Add" + DateTime.Now.ToString("yyyyMMddHH");
                model.Id = model.NewGuid2();
                model.IndicatorValue = i;
                model.IntNotNull = i;
                model.Bit = false;
                model.CreateDt = DateTime.Now.AddDays(i);
                model.CreateDate = DateTime.Now.AddDays(i);
                model.UpdateDate = DateTime.Now.AddDays(i);
                model.Creator = "admin";
                models.Add(model);
            }
            Stopwatch w = new Stopwatch();
            w.Start();
            var result = services.Add(models);
            w.Stop();
            Console.WriteLine("AddMany ->{0},耗时：{1}", result, w.ElapsedMilliseconds);
            return models;
        }
        #endregion

        #region 修改
        /// <summary>
        /// 单个实体更新
        /// </summary>
        private void Update()
        {
            var model = new IndicatorDTO();
            var id = model.NewGuid2();
            this.Add(id);
            model = services.FindOne(id);
            model.IndicatorName = "测试Update" + DateTime.Now.ToString("yyyyMMddHH");
            model.IndicatorFiledName = "Update" + DateTime.Now.ToString("yyyyMMddHH");
            model.UpdateDate = DateTime.Now;
            model.Updater = "admin_updater";
            var result = services.Update(model);
            Console.WriteLine("Update()测试:" + result);
        }
        /// <summary>
        /// 批量更新实体
        /// </summary>
        private void UpdateMany()
        {
            var models = this.AddMany(500);
            if (models.HasValues())
            {
                int i = 0;
                models.ForEach(c =>
                {
                    c.IndicatorName = "测试UpdateMany" + i.ToString();
                    c.IndicatorFiledName = "测试UpdateMany" + i.ToString();
                    c.IndicatorValue = i;
                    c.CreateDt = DateTime.Now;
                    c.UpdateDate = DateTime.Now;
                    i++;
                });
            }
            Stopwatch w = new Stopwatch();
            w.Start();
            var result = services.Update(models);
            w.Stop();
            Console.WriteLine("UpdateMany()测试:{0},耗时:{1}", result, w.ElapsedMilliseconds);
        }

        /// <summary>
        /// 动态类型更新
        /// </summary>
        private void UpdateSetionByHashtable()
        {
            var modelS = new IndicatorDTO();
            var id = modelS.NewGuid2();
            this.Add(id);
            dynamic model = new DynamicEntity();
            model.IndicatorName = "UpdateSetionByHashtable test";
            var condition = new Conditioner();
            //三种写法都可以
            //condition.Add("Id='" + id + "'", null, null, "(", ")");
            //condition.Add("Id='" + id + "'");
            condition.Where("Id='{0}'", new List<object>() { id });
            Hashtable updater = model.ToHashtable();
            string where = condition.ToWhere;
            bool result = services.UpdateSetion(updater, where) > 0;
            Console.WriteLine("UpdateSetion() DynamicEntity 测试:" + result);
        }

        /// <summary>
        /// 实体更新
        /// </summary>
        private void UpdateSetionByModel()
        {
            var modelS = new IndicatorDTO();
            var id = modelS.NewGuid2();
            this.Add(id);
            IndicatorDTO model = new IndicatorDTO();
            model.IndicatorName = "UpdateSetionByModel";
            var condition = new Conditioner();
            //三种写法都可以
            //condition.Add("Id='" + id + "'", null, null, "(", ")");
            //condition.Add("Id='" + id + "'");
            condition.Where("Id='{0}'", new List<object>() { id });
            bool result = services.UpdateSetion(model, condition) > 0;
            Console.WriteLine("UpdateSetionByModel() Model 测试:" + result);
        }
        private void UpdateSetionByQuerier()
        {
            var modelS = new IndicatorDTO();
            var id = modelS.NewGuid2();
            this.Add(id);
            IndicatorDTO model = new IndicatorDTO();
            model.IndicatorName = "UpdateSetionByQuerier";
            Querier query = new Querier("Id=({@0})", new List<object>() { id });//推荐使用此方式 组装条件
            var condition = new Conditioner();
            //三种写法都可以
            //condition.Add("Id='" + id + "'", null, null, "(", ")");
            //condition.Add("Id='" + id + "'");
            condition.Where("Id='{0}'", new List<object>() { id });
            bool result = services.UpdateSetion(model, query) > 0;
            Console.WriteLine("UpdateSetionByQuerier() Model 测试:" + result);
        }
        /// <summary>
        /// lamda表达式更新
        /// </summary>
        private void UpdateSetionByLamda()
        {
            var modelS = new IndicatorDTO();
            var id = modelS.NewGuid2();
            this.Add(id);
            Expression<Func<IndicatorDTO, IndicatorDTO>> updater = c => new IndicatorDTO() { IndicatorName = "UpdateSetionByLamda" };//可以使用ToHashtable() ToUpdater()
            Expression<Func<IndicatorDTO, bool>> p = (c) => c.Id == id;//使用ToWhere()转为条件 不建议使用此方式  推荐使用Querier
            bool result = services.UpdateSetion(updater.ToHashtable(), p.ToWhere()) > 0;

            //Stopwatch wathc = new Stopwatch();
            //wathc.Start();
            //Expression<Func<IndicatorDTO, IndicatorDTO>> updater = c => new IndicatorDTO() { IndicatorName = "UpdateSetion<IndicatorDTO>" };
            //var updaterxml = SerializeHelper.SerializeExpression(updater);
            //wathc.Stop();
            //Console.WriteLine(wathc.ElapsedMilliseconds);
            //wathc.Restart();
            //updater = SerializeHelper.DeserializeExpression<IndicatorDTO, IndicatorDTO>(updaterxml);
            //wathc.Stop();
            //Console.WriteLine(wathc.ElapsedMilliseconds);

            //wathc.Restart();
            //Expression<Func<IndicatorDTO, bool>> p = (c) => c.Id == 2;
            //var pXml = SerializeHelper.SerializeExpression(p);
            //p = SerializeHelper.DeserializeExpression<IndicatorDTO, bool>(pXml);
            //bool result = services.UpdateSetion<IndicatorDTO>(updater, p) > 0;
            //wathc.Stop();
            //Console.WriteLine(wathc.ElapsedMilliseconds);
            Console.WriteLine("UpdateSetionByLamda()测试:" + result);
        }

        /// <summary>
        /// 主键存在更新
        /// </summary>
        private void SaveByUpdate()
        {
            var modelS = new IndicatorDTO();
            var id = modelS.NewGuid2();
            this.Add(id);

            var model = new IndicatorDTO();
            model.IndicatorName = "测试SaveByUpdate" + DateTime.Now.ToString("yyyyMMddHH");
            model.IndicatorFiledName = "SaveByUpdate" + DateTime.Now.ToString("yyyyMMddHH");
            model.IndicatorValue = 123;
            model.CreateDt = DateTime.Now;
            model.Id = id;
            var result = services.Save(model);
            Console.WriteLine("SaveByUpdate()测试:" + result);
        }

        /// <summary>
        /// 主健不存在新增
        /// </summary>
        private void SaveByInsert()
        {
            var model = new IndicatorDTO();
            model.Id = model.NewGuid2();
            model.IndicatorName = "测试SaveByInsert" + DateTime.Now.ToString("yyyyMMddHH");
            model.IndicatorFiledName = "SaveByInsert" + DateTime.Now.ToString("yyyyMMddHH");
            model.IndicatorValue = 123;
            model.Bit = false;
            model.CreateDt = DateTime.Now;
            var result = services.Save(model);
            Console.WriteLine("SaveByInsert()测试:" + result);
        }

        /// <summary>
        /// 批量保存且新增
        /// </summary>
        private void SaveMany()
        {
            //var models = new List<IndicatorDTO>();
            //for (int i = 1; i <= 400; i++)
            //{
            //    var modelS = new IndicatorDTO();
            //    var id = modelS.NewGuid2();
            //    this.Add(id);

            //    var model = new IndicatorDTO();
            //    model.Id = id;
            //    model.IndicatorName = "SaveMany update" + i.ToString();
            //    model.IndicatorFiledName = "SaveMany update" + i.ToString();
            //    model.IndicatorValue = i;
            //    model.CreateDt = DateTime.Now;
            //    models.Add(model);
            //}
            //for (int i = 1; i <= 400; i++)
            //{
            //    var model = new IndicatorDTO();
            //    model.Id = model.NewGuid2();
            //    model.IndicatorName = "SaveMany add" + i.ToString();
            //    model.IndicatorFiledName = "SaveMany add" + i.ToString();
            //    model.Bit = false;
            //    model.CreateDt = DateTime.Now;
            //    models.Add(model);
            //}
            var models = AddMany(1000);
            Stopwatch w = new Stopwatch();
            w.Start();
            var result = services.Save(models);
            w.Stop();
            Console.WriteLine("SaveMany()测试:{0},耗时:{1}", result, w.ElapsedMilliseconds);
        }

        private void UpdateIsEnable()
        {
            var model = new IndicatorDTO();
            model.Id = model.NewGuid2();
            this.Add(model.Id);
            Querier q = new Querier();
            q.Where("Id={@0}", model.Id);
            Stopwatch w = new Stopwatch();
            w.Start();
            var result = services.UpdateIsEnable(q);
            w.Stop();
            Console.WriteLine("SaveMany()测试:{0},耗时:{1}", result, w.ElapsedMilliseconds);
        }
        #endregion

        #region 删除
        /// <summary>
        /// 主键删除
        /// </summary>
        private void DeleteByPK()
        {
            var modelS = new IndicatorDTO();
            var id = modelS.NewGuid2();
            this.Add(id);
            var result = services.Delete(id);
            Console.WriteLine("Delete()测试:" + result);
        }

        /// <summary>
        /// Conditioner组装条件
        /// </summary>
        private void DeleteByConditioner()
        {
            var modelAdd = new IndicatorDTO();
            modelAdd.IndicatorName = "Delete2" + DateTime.Now.ToString("yyyyMMddHH");
            modelAdd.IndicatorFiledName = "Delete2" + DateTime.Now.ToString("yyyyMMddHH");
            modelAdd.Id = modelAdd.NewGuid2();
            modelAdd.IndicatorValue = 123;
            modelAdd.IntNotNull = 1;
            modelAdd.Bit = false;
            modelAdd.CreateDt = DateTime.Now;
            modelAdd.CreateDate = DateTime.Now;
            modelAdd.UpdateDate = DateTime.Now;
            modelAdd.Creator = "admin";
            services.Add(modelAdd);

            IndicatorDTO model = new IndicatorDTO();
            var condition = new Conditioner();
            condition.Add("[IndicatorName]='" + modelAdd.IndicatorName + "'", "AND", null, "(", ")");
            condition.Add("[IndicatorFiledName]='" + modelAdd.IndicatorName + "'", null, null, "(", ")");
            bool result = services.Delete(condition);
            Console.WriteLine("Delete2()测试:" + result);
        }

        /// <summary>
        /// lamda条件
        /// </summary>
        private void DeleteByLamda()
        {
            var modelAdd = new IndicatorDTO();
            modelAdd.IndicatorName = "Delete3" + DateTime.Now.ToString("yyyyMMddHH");
            modelAdd.IndicatorFiledName = "Delete3" + DateTime.Now.ToString("yyyyMMddHH");
            modelAdd.Id = modelAdd.NewGuid2();
            modelAdd.IndicatorValue = 123;
            modelAdd.IntNotNull = 1;
            modelAdd.Bit = false;
            modelAdd.CreateDt = DateTime.Now;
            modelAdd.CreateDate = DateTime.Now;
            modelAdd.UpdateDate = DateTime.Now;
            modelAdd.Creator = "admin";
            services.Add(modelAdd);

            Expression<Func<IndicatorDTO, bool>> p = c => c.IndicatorName.StartsWith("Delete3");
            bool result = services.Delete(p.ToWhere());
            Console.WriteLine("Delete3()测试:" + result);
        }

        /// <summary>
        /// 删除by Querier
        /// </summary>
        private void DeleteByQuerier()
        {
            var modelAdd = new IndicatorDTO();
            modelAdd.IndicatorName = "DeleteByQuerier" + DateTime.Now.ToString("yyyyMMddHH");
            modelAdd.IndicatorFiledName = "DeleteByQuerier" + DateTime.Now.ToString("yyyyMMddHH");
            modelAdd.Id = modelAdd.NewGuid2();
            modelAdd.IndicatorValue = 123;
            modelAdd.IntNotNull = 1;
            modelAdd.Bit = false;
            modelAdd.CreateDt = DateTime.Now;
            modelAdd.CreateDate = DateTime.Now;
            modelAdd.UpdateDate = DateTime.Now;
            modelAdd.Creator = "admin";
            services.Add(modelAdd);

            Querier query = new Querier("IndicatorName.StartsWith({@0})", new List<object>() { "DeleteByQuerier" });//推荐使用此方式 组装条件
            bool result = services.Delete(query);
            Console.WriteLine("DeleteByQuerier()测试:" + result);
        }
        #endregion

    }
}
